package com.eastmoney.emis.edda.infrastructure.hsbc.dto;

import com.eastmoney.emis.edda.domain.valueobject.ResultStatus;
import com.eastmoney.emis.edda.infrastructure.hsbc.annotation.HsbcEncrypt;
import com.eastmoney.emis.edda.projection.HsbcEddaContext;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @description: Description
 * @projectName: EDDA-HSBC
 * @package: com.eastmoney.emis.edda.infrastructure.dto
 * @author: 汪程程
 * @date: 2022/9/27 1:19 PM
 * @version: 1.0
 */
@HsbcEncrypt
public class HsbcEddaBaseResp {

    public HsbcEddaProcessDto ProcessResult;
    public String Id;
    public String Code;
    public String Message;
    public List<HsbcEddaError> Errors;

    private boolean networkError;

    private HsbcEddaContext context;

    public HsbcEddaBaseResp() {
    }

    public boolean success() {
        return ProcessResult != null && ObjectUtils.isEmpty(Errors);
    }

    public String errors() {
        return Errors != null ? Errors.stream().map(HsbcEddaError::errors).collect(Collectors.joining()) : Message;
    }
    public String errorCodes() {
        return Errors != null ? Errors.stream().map(e -> e.ErrorCode).collect(Collectors.joining()) : Message;
    }

    public String contextString() {
        return context().getReqPayload() + "\n" + context().getRespPayload();
    }


    public HsbcEddaContext context() {
        return context;
    }

    public void context(HsbcEddaContext context) {
        this.context = context;
    }

    public String result() {
        if (success()) {
            if (ProcessResult.RejectReasonList == null) {
                return ResultStatus.SUCCESS.name();
            }
            return ProcessResult.RejectReasonList.stream().map(r -> r.RejectReasonCode + ":" + r.RejectReasonInfomation).collect(Collectors.joining());
        }
        return errors();
    }

    public boolean isNetworkError() {
        return networkError;
    }

    public void setNetworkError(boolean networkError) {
        this.networkError = networkError;
    }

    public String rejectReasonCode() {
        if (success()) {
            return extractInfo(r -> r.RejectReasonCode);
        }
        return errorCodes();
    }

    public String rejectReason() {
        if (success()) {
            return extractInfo(r -> r.RejectReasonInfomation);
        }
        return errors();
    }

    private String extractInfo(Function<HsbcEddaProcessDto.RejectReasonList, String> mapper) {
        List<HsbcEddaProcessDto.RejectReasonList> target = ProcessResult.RejectReasonList;
        return Objects.isNull(target) ? null : target.stream().map(mapper).collect(Collectors.joining());
    }

    public HsbcEddaBaseResp onSuccess(Consumer<HsbcEddaBaseResp> hsbcEddaBaseRespConsumer) {
        if(success()) {
            hsbcEddaBaseRespConsumer.accept(this);
        }
        return this;
    }

    public HsbcEddaBaseResp onFail(Consumer<HsbcEddaBaseResp> failConsumer) {
        if(!success() && !isNetworkError()) {
            failConsumer.accept(this);
        }
        return this;
    }

    public HsbcEddaBaseResp onNetworkError(Consumer<HsbcEddaBaseResp> networkErrorConsumer) {
        if(!success() && isNetworkError()) {
            networkErrorConsumer.accept(this);
        }
        return this;
    }


    public static class HsbcEddaError {
        public String ErrorCode;
        public String Message;

        @Override
        public String toString() {
            return "HsbcEddaError{" +
                    "ErrorCode='" + ErrorCode + '\'' +
                    ", Message='" + Message + '\'' +
                    '}';
        }

        public String errors() {
            String errorInfo = extractErrorInfo();
            return errorInfo != null ? errorInfo : ErrorCode;
        }

        public String extractErrorInfo() {
            if (StringUtils.hasText(Message)) {
                int start = Message.lastIndexOf("- [");
                int end = Message.length();
                if(start == -1) {
                    start = Message.lastIndexOf("- ") + 2;
                } else {
                    start = start + 3;
                    end = end - 1;
                }
                return start > 0 && end > 0 ? Message.substring(start, end) : Message;
            }
            return null;
        }
    }
}
